using Microsoft.EntityFrameworkCore;
using WeatherSystem.API.Data;
using WeatherSystem.API.Services;
using WeatherSystem.API.Hubs;
using WeatherSystem.API.Middleware;
using Microsoft.AspNetCore.ResponseCompression;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IO.Compression;
using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using AspNetCoreRateLimit;
using StackExchange.Redis;
using WeatherSystem.API.Models;
using Microsoft.Extensions.Caching.Distributed;
using WeatherSystem.API.Repositories;
using WeatherSystem.API.CQRS;
using WeatherSystem.API.CQRS.Handlers;
using WeatherSystem.API.CQRS.Commands;
using WeatherSystem.API.CQRS.Queries;
using WeatherSystem.API.BackgroundJobs;
using Hangfire;
using Hangfire.MemoryStorage;
using WeatherSystem.API.HealthChecks;
using WeatherSystem.API.Configurations;

var builder = WebApplication.CreateBuilder(args);

// 加载环境变量
if (File.Exists(".env"))
{
    foreach (var line in File.ReadAllLines(".env"))
    {
        if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
            continue;

        var parts = line.Split('=', 2);
        if (parts.Length == 2)
        {
            Environment.SetEnvironmentVariable(parts[0].Trim(), parts[1].Trim());
        }
    }
}

// 确保配置系统包含环境变量
builder.Configuration.AddEnvironmentVariables();

// Add services to the container.
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
        options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
        options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
        options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
    });

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
// 添加Swagger文档支持  
builder.Services.AddSwaggerGen();

// 数据库配置
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? Environment.GetEnvironmentVariable("DATABASE_CONNECTION_STRING") 
    ?? "Data Source=WeatherSystem.db";

builder.Services.AddDbContext<WeatherDbContext>(options =>
    options.UseSqlite(connectionString));

// HTTP客户端配置 - 使用Mock服务，不需要真实的HTTP客户端
// builder.Services.AddHttpClient<IWeatherApiService, OpenWeatherMapService>(client =>
// {
//     client.BaseAddress = new Uri("https://api.openweathermap.org/data/2.5/");
//     client.Timeout = TimeSpan.FromSeconds(30);
// });

// 服务注册
builder.Services.AddScoped<IWeatherService, WeatherService>();
builder.Services.AddScoped<IWeatherApiService, MockWeatherApiService>();
builder.Services.AddSingleton<IDataCollectionService, DataCollectionService>();
builder.Services.AddScoped<IStatisticsService, StatisticsService>();
builder.Services.AddSingleton<IWeatherNotificationService, WeatherNotificationService>();
// 新增：指标配置服务注册
builder.Services.AddScoped<IMetricConfigurationService, MetricConfigurationService>();
// 认证服务注册
builder.Services.AddScoped<IAuthService, AuthService>();
// 密码哈希服务
builder.Services.AddScoped<Microsoft.AspNetCore.Identity.IPasswordHasher<User>, Microsoft.AspNetCore.Identity.PasswordHasher<User>>();
// 缓存服务
builder.Services.AddScoped<ICacheService, CacheService>();
// 分布式缓存服务
builder.Services.AddScoped<IDistributedCacheService, DistributedCacheService>();
builder.Services.AddScoped<ICacheInvalidationService, CacheInvalidationService>();
// 导出服务
builder.Services.AddScoped<IExportService, ExportService>();

// OpenTelemetry监控和指标
builder.Services.AddOpenTelemetryServices(builder.Configuration);
builder.Services.AddScoped<IBusinessMetricsService, BusinessMetricsService>();

// RabbitMQ消息队列
builder.Services.AddRabbitMQServices(builder.Configuration);

// Repository模式和工作单元
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();

// Read-Write separated repositories
builder.Services.AddScoped<IWeatherDataReadRepository, WeatherDataReadRepository>();
builder.Services.AddScoped<IWeatherDataWriteRepository, WeatherDataWriteRepository>();
builder.Services.AddScoped(typeof(IReadRepository<>), typeof(ReadRepository<>));
builder.Services.AddScoped(typeof(IWriteRepository<>), typeof(WriteRepository<>));

// MediatR 注册
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

// Legacy CQRS (可以逐步迁移)
// builder.Services.AddScoped<IMediator, Mediator>();

// FluentValidation配置
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressModelStateInvalidFilter = true;
});

// 后台服务
builder.Services.AddHostedService<BackgroundDataCollectionService>();

// Hangfire 后台作业处理配置
builder.Services.AddHangfire(configuration => configuration
    .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    .UseMemoryStorage());

builder.Services.AddHangfireServer();

// 后台作业服务注册
builder.Services.AddScoped<IBackgroundJobService, BackgroundJobService>();
builder.Services.AddScoped<IBackgroundJobTaskService, BackgroundJobTaskService>();

// 错误恢复服务注册
builder.Services.AddScoped<IErrorRecoveryService, ErrorRecoveryService>();

// SignalR配置
builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = builder.Environment.IsDevelopment();
    options.KeepAliveInterval = TimeSpan.FromSeconds(15);
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(30);
});

// 响应压缩
builder.Services.AddResponseCompression(opts =>
{
    opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] 
    { 
        "application/octet-stream",
        "application/json",
        "text/plain",
        "text/html",
        "text/css",
        "application/javascript",
        "application/xml",
        "text/xml"
    });
    opts.Providers.Add<BrotliCompressionProvider>();
    opts.Providers.Add<GzipCompressionProvider>();
});

builder.Services.Configure<BrotliCompressionProviderOptions>(options =>
{
    options.Level = CompressionLevel.Optimal;
});

builder.Services.Configure<GzipCompressionProviderOptions>(options =>
{
    options.Level = CompressionLevel.SmallestSize;
});

// CORS配置
var allowedOrigins = Environment.GetEnvironmentVariable("CORS_ALLOWED_ORIGINS")
    ?? "http://localhost:3000,http://localhost:3001";

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowFrontend", policy =>
    {
        policy.WithOrigins(allowedOrigins.Split(','))
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials(); // SignalR需要
    });
});

// 内存缓存
builder.Services.AddMemoryCache();

// 分布式缓存配置
var redisConnectionString = Environment.GetEnvironmentVariable("REDIS_CONNECTION_STRING");
if (!string.IsNullOrEmpty(redisConnectionString))
{
    // Redis分布式缓存
    builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
    {
        return ConnectionMultiplexer.Connect(redisConnectionString);
    });
}

// 使用内存分布式缓存（Redis可选）
builder.Services.AddDistributedMemoryCache();

// 速率限制配置
builder.Services.Configure<IpRateLimitOptions>(options =>
{
    options.EnableEndpointRateLimiting = true;
    options.StackBlockedRequests = false;
    options.HttpStatusCode = 429;
    options.RealIpHeader = "X-Real-IP";
    options.ClientIdHeader = "X-ClientId";
    options.GeneralRules = new List<RateLimitRule>
    {
        new RateLimitRule
        {
            Endpoint = "*",
            Period = "1m",
            Limit = 100
        },
        new RateLimitRule
        {
            Endpoint = "*/api/auth/login",
            Period = "15m", 
            Limit = 5
        },
        new RateLimitRule
        {
            Endpoint = "*/api/auth/register",
            Period = "1h",
            Limit = 3
        }
    };
});

builder.Services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
builder.Services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
builder.Services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();

// JWT认证配置 - 增强版本
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = Environment.GetEnvironmentVariable("JWT_SECRET_KEY") 
    ?? jwtSettings["SecretKey"] 
    ?? throw new InvalidOperationException("JWT_SECRET_KEY 环境变量未配置");

var issuer = jwtSettings["Issuer"] ?? "WeatherSystem";
var audience = jwtSettings["Audience"] ?? "WeatherSystemUsers";

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = issuer,
        ValidAudience = audience,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)),
        ClockSkew = TimeSpan.FromMinutes(1), // 允许1分钟时钟偏差
        RequireExpirationTime = true,
        ValidateActor = false,
        ValidateTokenReplay = false
    };

    // SignalR和API支持
    options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
            var accessToken = context.Request.Query["access_token"];
            var path = context.HttpContext.Request.Path;
            if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/weatherHub"))
            {
                context.Token = accessToken;
            }
            return Task.CompletedTask;
        },
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };
});

// 基于角色的授权策略
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => 
        policy.RequireRole("Admin"));
    
    options.AddPolicy("UserOrAdmin", policy => 
        policy.RequireRole("User", "Admin"));
    
    options.AddPolicy("ReadOnlyOrHigher", policy => 
        policy.RequireRole("ReadOnly", "User", "Admin"));
});

// 配置Serilog结构化日志
builder.ConfigureSerilog();

// 添加结构化日志服务
builder.Services.AddStructuredLogging(builder.Configuration);

// 健康检查
builder.Services.AddHttpClient<ExternalServiceHealthCheck>();
builder.Services.AddHealthChecks()
    .AddCheck<DatabaseHealthCheck>("database", tags: new[] { "database", "core" })
    .AddCheck<ExternalServiceHealthCheck>("external-weather-api", tags: new[] { "external", "api" })
    .AddCheck<CustomHealthCheck>("system-health", tags: new[] { "system", "comprehensive" })
    .AddCheck("memory", () =>
    {
        var memoryUsed = GC.GetTotalMemory(false);
        var memoryLimit = 1024 * 1024 * 1024; // 1GB 限制示例
        
        return memoryUsed < memoryLimit * 0.8 
            ? Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy($"内存使用正常: {memoryUsed / 1024 / 1024}MB")
            : memoryUsed < memoryLimit 
                ? Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Degraded($"内存使用较高: {memoryUsed / 1024 / 1024}MB")
                : Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Unhealthy($"内存使用过高: {memoryUsed / 1024 / 1024}MB");
    }, tags: new[] { "memory", "performance" });

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    // 启用Swagger文档
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Weather System API v1");
        c.RoutePrefix = "api-docs";
    });
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseHsts();
}

// 全局异常处理中间件（在所有其他中间件之前）
app.UseMiddleware<GlobalExceptionMiddleware>();

// 业务指标收集中间件
app.UseMetricsMiddleware();

// 响应压缩
app.UseResponseCompression();

// HTTPS重定向和安全头
app.UseHttpsRedirection();

// 安全头配置
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
    context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
    context.Response.Headers.Add("Content-Security-Policy", "default-src 'self'");
    context.Response.Headers.Add("Permissions-Policy", "geolocation=(), microphone=(), camera=()");
    
    await next();
});

// 缓存头配置
app.Use(async (context, next) =>
{
    var path = context.Request.Path.ToString().ToLower();
    
    if (path.Contains("/api/weather/"))
    {
        // 天气数据API缓存策略
        if (path.Contains("/current/") || path.Contains("/latest"))
        {
            // 最新数据缓存5分钟
            context.Response.Headers.Add("Cache-Control", "public, max-age=300");
        }
        else if (path.Contains("/history/") || path.Contains("/statistics/"))
        {
            // 历史数据和统计数据缓存30分钟
            context.Response.Headers.Add("Cache-Control", "public, max-age=1800");
        }
        else
        {
            // 其他API数据缓存10分钟
            context.Response.Headers.Add("Cache-Control", "public, max-age=600");
        }
    }
    else if (path.Contains("/api/"))
    {
        // 其他API禁用缓存
        context.Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
        context.Response.Headers.Add("Pragma", "no-cache");
        context.Response.Headers.Add("Expires", "0");
    }
    
    await next();
});

// 静态文件
app.UseStaticFiles();

// 路由
app.UseRouting();

// CORS
app.UseCors("AllowFrontend");

// 速率限制中间件
app.UseIpRateLimiting();

// HTTP请求日志中间件
app.UseCustomHttpLogging();

// 认证和授权中间件
app.UseAuthentication();
app.UseAuthorization();

// Hangfire Dashboard (仅在开发环境或管理员访问时启用)
if (app.Environment.IsDevelopment())
{
    app.UseHangfireDashboard("/jobs", new DashboardOptions
    {
        Authorization = new[] { new HangfireDashboardAuthorizationFilter() },
        DashboardTitle = "Weather System Jobs"
    });
}
else
{
    // 生产环境需要更严格的授权
    app.UseHangfireDashboard("/jobs", new DashboardOptions
    {
        Authorization = new[] { new HangfireDashboardAuthorizationFilter() },
        DashboardTitle = "Weather System Jobs",
        StatsPollingInterval = 5000
    });
}

// 控制器路由
app.MapControllers();

// SignalR Hub
app.MapHub<WeatherHub>("/weatherHub");

// 健康检查端点
app.MapHealthChecks("/health");

// Prometheus指标端点
app.UseOpenTelemetryPrometheusMetrics();

// 数据库初始化
using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
    
    try
    {
        // 确保数据库已创建
        await context.Database.EnsureCreatedAsync();
        
        // 运行迁移（如果有）
        if (context.Database.GetPendingMigrations().Any())
        {
            await context.Database.MigrateAsync();
            logger.LogInformation("数据库迁移完成");
        }
        
        logger.LogInformation("数据库初始化完成");
        
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "数据库初始化失败");
        throw;
    }
}

// 初始化后台作业
using (var scope = app.Services.CreateScope())
{
    var jobService = scope.ServiceProvider.GetRequiredService<IBackgroundJobService>();
    var jobLogger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
    
    try
    {
        // 设置定期作业
        jobService.SetupRecurringJobs();
        jobLogger.LogInformation("后台作业调度设置完成");
    }
    catch (Exception ex)
    {
        jobLogger.LogError(ex, "设置后台作业时发生错误");
    }
}

// 启动信息
var startupLogger = app.Services.GetRequiredService<ILogger<Program>>();
startupLogger.LogInformation("天气数据采集与统计系统启动完成");
startupLogger.LogInformation("API文档地址: {SwaggerUrl}", app.Environment.IsDevelopment() ? "http://localhost:5000" : "生产环境URL");
startupLogger.LogInformation("SignalR Hub地址: {HubUrl}", "/weatherHub");
startupLogger.LogInformation("Hangfire作业面板地址: {JobsUrl}", "/jobs");

// 检查关键配置
var apiKey = Environment.GetEnvironmentVariable("OPENWEATHERMAP_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
    startupLogger.LogWarning("OpenWeatherMap API密钥未配置，数据采集功能将无法正常工作");
}

var dataCollectionEnabled = Environment.GetEnvironmentVariable("DATA_COLLECTION_ENABLED");
if (string.Equals(dataCollectionEnabled, "true", StringComparison.OrdinalIgnoreCase))
{
    startupLogger.LogInformation("自动数据采集已启用");
}
else
{
    startupLogger.LogInformation("自动数据采集已禁用，可通过API手动触发");
}

app.Run();

// 为了支持基于 WebApplicationFactory<Program> 的集成测试，
// 在最小主机构建模式下补充一个可见的 Program 部分类。
public partial class Program { }
